package com.netscenery.yang;

import java.util.ArrayList;

import com.netscenery.yang.parser.YangParserEnv;


/**
 * @author llly
 *
 */
public class YangStatement {
	private String keyword;
	private String argument;
//	private boolean isSingleStatment = true;
	private YangParserEnv parserEnv = new YangParserEnv();
	private boolean isNeedQuotes = false;
	private ArrayList<YangStatement> subElements;
	
	
	
	/**
	 * @param isNeedQuotes the isNeedQuotes to set
	 */
	public void setNeedQuotes(boolean isNeedQuotes) {
		this.isNeedQuotes = isNeedQuotes;
	}
	/**
	 * @return the parserEnv
	 */
	public YangParserEnv getParserEnv() {
		return parserEnv;
	}
	/**
	 * @param parserEnv the parserEnv to set
	 */
	public void setParserEnv(YangParserEnv parserEnv) {
		this.parserEnv = parserEnv;
	}
//	public boolean isSingleStatment() {
//		return isSingleStatment;
//	}
//	public void setSingleStatment(boolean isSingleStatment) {
//		this.isSingleStatment = isSingleStatment;
//	}
	public boolean isIsNeedQuotes() {
		if (true == isNeedQuotes){
			return true;
		}
		if (null == this.argument){
			return false;
		}
		
		if (this.argument.contains(" ") 
				|| this.argument.contains("\t")
				|| this.argument.contains(";")
				|| this.argument.contains("{")
				|| this.argument.contains("}")
				|| this.argument.contains("\"")
				|| this.argument.contains("'")
				|| this.argument.contains("//")
				|| this.argument.contains("/*")
				|| this.argument.contains("*/")
				|| this.argument.contains("\n")){
			return true;
		}
		return false;
	}



	//private List subElements;
	

	public static final String YANG_STATEMENT_ANYXML = "anyxml";
	public static final String YANG_STATEMENT_ARGUMENT = "argument";
	public static final String YANG_STATEMENT_AUGMENT = "augment";
	public static final String YANG_STATEMENT_BASE = "base";
	public static final String YANG_STATEMENT_BELONGSTO = "belongs-to";
	public static final String YANG_STATEMENT_BIT = "bit";
	public static final String YANG_STATEMENT_CASE = "case";
	public static final String YANG_STATEMENT_CHOICE = "choice";
	public static final String YANG_STATEMENT_CONFIG = "config";
	public static final String YANG_STATEMENT_CONTACT = "contact";
	public static final String YANG_STATEMENT_CONTAINER = "container";
	public static final String YANG_STATEMENT_DEFAULT = "default";
	public static final String YANG_STATEMENT_DESCRIPTION = "description";	
	public static final String YANG_STATEMENT_DEVIATION = "deviation";
	public static final String YANG_STATEMENT_DEVIATE = "deviate";
	public static final String YANG_STATEMENT_ENUM = "enum";
	public static final String YANG_STATEMENT_ERRORAPPTAG = "error-app-tag";
	public static final String YANG_STATEMENT_ERRORMESSAGE = "error-message";
	public static final String YANG_STATEMENT_EXTENSION = "extension";
	public static final String YANG_STATEMENT_FEATURE = "feature";
	public static final String YANG_STATEMENT_FRACTIONDIGITS = "fraction-digits";
	public static final String YANG_STATEMENT_GROUPING = "grouping";
	public static final String YANG_STATEMENT_IDENTITY = "identity";
	public static final String YANG_STATEMENT_IFFEATURE = "if-feature";
	public static final String YANG_STATEMENT_IMPORT = "import";
	public static final String YANG_STATEMENT_INCLUDE = "include";
	public static final String YANG_STATEMENT_INPUT = "input";	
	public static final String YANG_STATEMENT_KEY = "key";	
	public static final String YANG_STATEMENT_LEAF = "leaf";	
	public static final String YANG_STATEMENT_LEAFLIST = "leaf-list";	
	public static final String YANG_STATEMENT_LENGTH = "length";	
	public static final String YANG_STATEMENT_LIST = "list";		
	public static final String YANG_STATEMENT_MANDATORY = "mandatory";	
	public static final String YANG_STATEMENT_MAXELEMENTS = "max-elements";	
	public static final String YANG_STATEMENT_MINELEMENTS = "min-elements";
	public static final String YANG_STATEMENT_MODULE = "module";
	public static final String YANG_STATEMENT_MUST = "must";
	public static final String YANG_STATEMENT_NAMESPACE = "namespace";
	public static final String YANG_STATEMENT_NOTIFICATION = "notification";	
	public static final String YANG_STATEMENT_ORDEREDBY = "ordered-by";	
	public static final String YANG_STATEMENT_ORGANIZATION = "organization";
	public static final String YANG_STATEMENT_OUTPUT = "output";	
	public static final String YANG_STATEMENT_PATH = "path";	
	public static final String YANG_STATEMENT_PATTERN = "pattern";	
	public static final String YANG_STATEMENT_POSITION = "position";	
	public static final String YANG_STATEMENT_PREFIX = "prefix";
	public static final String YANG_STATEMENT_PRESENCE = "presence";
	public static final String YANG_STATEMENT_RANGE = "range";
	public static final String YANG_STATEMENT_REFERENCE = "reference";	
	public static final String YANG_STATEMENT_REFINE = "refine";	
	public static final String YANG_STATEMENT_REQUIREINSTANCE = "require-instance";	
	public static final String YANG_STATEMENT_REVISION = "revision";
	public static final String YANG_STATEMENT_REVISIONDATE = "revision-date";
	public static final String YANG_STATEMENT_RPC = "rpc";
	public static final String YANG_STATEMENT_STATUS = "status";
	public static final String YANG_STATEMENT_SUBMODULE = "submodule";
	public static final String YANG_STATEMENT_TYPE = "type";
	public static final String YANG_STATEMENT_TYPEDEF = "typedef";	
	public static final String YANG_STATEMENT_UNIQUE = "unique";	
	public static final String YANG_STATEMENT_UNITS = "units";
	public static final String YANG_STATEMENT_USES = "uses";
	public static final String YANG_STATEMENT_VALUE = "value";
	public static final String YANG_STATEMENT_WHEN = "when";
	public static final String YANG_STATEMENT_YANGVERSION = "yang-version";
	public static final String YANG_STATEMENT_YINELEMENT = "yin-element";
	public static final String YANG_STATEMENT_EXT_SELECT = "select";
	

/*
	public static final String YANG_STATEMENT_ADD = "add";
	public static final String YANG_STATEMENT_CURRENT = "current";
		
							   delete-keyword      = 'delete'
							   deprecated-keyword  = 'deprecated'
							   false-keyword       = 'false'
							   max-keyword         = 'max'
							   min-keyword         = 'min'
							   not-supported-keyword = 'not-supported'
							   obsolete-keyword    = 'obsolete'
							   replace-keyword     = 'replace'
							   system-keyword      = 'system'
							   true-keyword        = 'true'
							   unbounded-keyword   = 'unbounded'
							   user-keyword        = 'user'*/
	
	public static final String[] keywords = {
			 YANG_STATEMENT_ANYXML, 
			 YANG_STATEMENT_ARGUMENT ,
			 YANG_STATEMENT_AUGMENT ,
			 YANG_STATEMENT_BASE ,
			 YANG_STATEMENT_BELONGSTO ,
			 YANG_STATEMENT_BIT ,
			 YANG_STATEMENT_CASE ,
			 YANG_STATEMENT_CHOICE,
			 YANG_STATEMENT_CONFIG,
			 YANG_STATEMENT_CONTACT,
			 YANG_STATEMENT_CONTAINER,
			 YANG_STATEMENT_DEFAULT ,
			 YANG_STATEMENT_DESCRIPTION ,	
			 YANG_STATEMENT_DEVIATION ,
			 YANG_STATEMENT_DEVIATE ,
			 YANG_STATEMENT_ENUM ,
			 YANG_STATEMENT_ERRORAPPTAG ,
			 YANG_STATEMENT_ERRORMESSAGE,
			 YANG_STATEMENT_EXTENSION,
			 YANG_STATEMENT_FEATURE ,
			 YANG_STATEMENT_FRACTIONDIGITS,
			 YANG_STATEMENT_GROUPING,
			 YANG_STATEMENT_IDENTITY,
			 YANG_STATEMENT_IFFEATURE,
			 YANG_STATEMENT_IMPORT ,
			 YANG_STATEMENT_INCLUDE,
			 YANG_STATEMENT_INPUT ,	
			 YANG_STATEMENT_KEY ,	
			 YANG_STATEMENT_LEAF,	
			 YANG_STATEMENT_LEAFLIST,	
			 YANG_STATEMENT_LENGTH ,	
			 YANG_STATEMENT_LIST ,		
			 YANG_STATEMENT_MANDATORY ,	
			 YANG_STATEMENT_MAXELEMENTS ,	
			 YANG_STATEMENT_MINELEMENTS,
			 YANG_STATEMENT_MODULE,
			 YANG_STATEMENT_MUST ,
			 YANG_STATEMENT_NAMESPACE,
			 YANG_STATEMENT_NOTIFICATION,	
			 YANG_STATEMENT_ORDEREDBY,	
			 YANG_STATEMENT_ORGANIZATION,
			 YANG_STATEMENT_OUTPUT,	
			 YANG_STATEMENT_PATH ,	
			 YANG_STATEMENT_PATTERN ,	
			 YANG_STATEMENT_POSITION,	
			 YANG_STATEMENT_PREFIX,
			 YANG_STATEMENT_PRESENCE,
			 YANG_STATEMENT_RANGE,
			 YANG_STATEMENT_REFERENCE ,	
			 YANG_STATEMENT_REFINE ,	
			 YANG_STATEMENT_REQUIREINSTANCE ,	
			 YANG_STATEMENT_REVISION,
			 YANG_STATEMENT_REVISIONDATE,
			 YANG_STATEMENT_RPC,
			 YANG_STATEMENT_STATUS,
			 YANG_STATEMENT_SUBMODULE,
			 YANG_STATEMENT_TYPE,
			 YANG_STATEMENT_TYPEDEF,	
			 YANG_STATEMENT_UNIQUE,	
			 YANG_STATEMENT_UNITS,
			 YANG_STATEMENT_USES ,
			 YANG_STATEMENT_VALUE ,
			 YANG_STATEMENT_WHEN,
			 YANG_STATEMENT_YANGVERSION ,
			 YANG_STATEMENT_YINELEMENT
	};
	
	

	
	public YangStatement(String keyword){
		
		this.keyword = keyword;
	}
	public YangStatement(String keyword, String argument){

		this.keyword =keyword;
		this.argument = argument;
	}
	public String getKeyword() {
		return keyword;
	}
	public void setKeyword(String keyword) {
		this.keyword = keyword;
	}
	public String getArgument() {
		return argument;
	}
	public void setArgument(String argument) {
		this.argument = argument;
	}
	
	public void addChild(YangStatement element){
		if (null == element){
			return;
		}
		if (null == this.subElements){
			this.subElements = new ArrayList<YangStatement>(1);
		}
		this.subElements.add(element);
	}
	
	public YangStatement getChild(int index){
		if (null == this.subElements){
			return null;
		}
		if (index >= this.subElements.size()){
			return null;
		}
		return this.subElements.get(index);
	}
	
	public ArrayList<YangStatement> getChildren(String name){
		YangStatement element;
		ArrayList<YangStatement> list = new ArrayList<YangStatement>(1);
		if (null == this.subElements){
			return null;
		}
		
		int size = this.subElements.size();
		
		for (int i=0;i<size;i++){
			element = this.getChild(i);
			if (null != element){
				if (element.getKeyword().equals(name)){
					list.add(element);
				}
			}
		}
		
		return list;
	}
	public YangStatement getChild(String name){
		ArrayList<YangStatement> list = getChildren(name);
		if (null == list){
			return null;
		}
		
		if (1 != list.size()){
			return null;
		}
		
		return list.get(0);
	}
	
	public String getChildArgument(String childName){
		YangStatement statement = getChild(childName);
		if (null != statement){
			return statement.argument;
		}
		
		return null;
	}
	public String getChildArgument(String childName, int index){
		YangStatement element;
		ArrayList<YangStatement> list = this.getChildren(childName);
		if (null == list){
			return null;
		}
		
		if (0 == list.size()){
			return null;
		}
		
		if (index >= list.size()){
			return null;
		}
		
		element = list.get(index);
		if (null == element){
			return null;
		}
		
		return element.argument;
	}
	
	public boolean equals(YangStatement element){
		
		int i = 0;
		int selfSize = 0;
		int sourceSize = 0;
		YangStatement selfSubElement;
		YangStatement sourceSubElement;
		if (null == element){
			return false;
		}
		if (!this.keyword.equals(element.keyword)){
			return false;
		}
		
		if (!this.argument.equals(element.argument)){
			return false;
		}
		
		selfSize = this.subElements.size();
		sourceSize = element.subElements.size();
		if (selfSize != sourceSize){
			return false;
		}
		
		if (0 == selfSize ){
			return true;
		}
		
		for (i = 0;i<selfSize;i++){
			selfSubElement = this.subElements.get(i);
			sourceSubElement = element.subElements.get(i);
			if (!selfSubElement.equals(sourceSubElement)){
				return false;
			}
		}
		
		return true;
		
	}
	
	public void removeChild(YangStatement element){
		if (null == this.subElements){
			return;
		}
		int i = 0;
		int size = this.subElements.size();
		
		for(i = 0; i < size;i++){
			YangStatement statement = this.subElements.get(i);
			if (statement.equals(element)){
				this.subElements.remove(i);
			}
		}
		return;
	}
	
	public void removeChild(String name){
		if (null == this.subElements){
			return;
		}
		int i = 0;
		int size = this.subElements.size();
		
		for(i = 0; i < size;i++){
			YangStatement statement = this.subElements.get(i);
			if (statement.getKeyword().equals(name)){
				this.subElements.remove(i);
			}
		}
		return;
	}
	
	public void removeChild(int index){
		if (null == this.subElements){
			return;
		}
		if (index >= this.subElements.size()){
			return;
		}
		this.subElements.remove(index);
		return;
	}
	
	public boolean hasChildren(){
		if (null == this.subElements){
			return false;
		}
		if (0 != this.subElements.size()){
			return true;
		}
		
		return false;
	}
	
	public int getChildrenNumber(){
		if (null == this.subElements){
			return 0;
		}
		return this.subElements.size();
	}
	public int getChildrenNumber(String childName){
		YangStatement element;
		int number= 0;

		if (null == this.subElements){
			return number;
		}
		
		int size = this.subElements.size();
		
		for (int i=0;i<size;i++){
			element = this.getChild(i);
			if (null != element){
				if (element.getKeyword().equals(keyword)){
					number++;
				}
			}
		}
		
		return number;
	}
	
	public static boolean isYangKeyword(String keyword){
		int size = YangStatement.keywords.length;
		for (int i=0;i<size;i++){
			String keywordtmp = YangStatement.keywords[i];
			if (keywordtmp.equals(keyword)){
				return true;
			}
		}
		
		return false;
	}
	
	public String toString(){
		StringBuffer sb = new StringBuffer();
		sb.append(this.getKeyword());
		sb.append(" ");
	    if (null != this.argument){
	    	sb.append(this.getArgument());
	    }
	    
	    if (null != this.subElements){
	    	int size = this.getChildrenNumber();
	    	if (0 != size){
	    		sb.append("{");
	    		for (int i = 0; i < size;i++){
		    		YangStatement child = this.getChild(i);
		    		if (null == child){
		    			continue;
		    		}
		    		sb.append(child.toString());
		    	}
	    		sb.append("}");
	    	}    	
	    }
	    return sb.toString();
	}
}
